home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / glibc108.gz / glibc108 / glibc-1.08.1 / sysdeps / alpha / memchr.c < prev    next >
C/C++ Source or Header  |  1993-12-23  |  2KB  |  88 lines

  1. /* Copyright (C) 1992, 1993 Free Software Foundation, Inc.
  2.  
  3. The GNU C Library is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU Library General Public License as
  5. published by the Free Software Foundation; either version 2 of the
  6. License, or (at your option) any later version.
  7.  
  8. The GNU C Library is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  11. Library General Public License for more details.
  12.  
  13. You should have received a copy of the GNU Library General Public
  14. License along with the GNU C Library; see the file COPYING.LIB.  If
  15. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  16. Cambridge, MA 02139, USA.  */
  17.  
  18. #include <string.h>
  19.  
  20. /* Search no more than N bytes of S for C.  */
  21.  
  22. void *
  23. memchr (const void *s, int c, size_t n)
  24. {
  25.   const char *char_ptr;
  26.   const unsigned long int *longword_ptr;
  27.   unsigned long int charmask;
  28.   size_t x;
  29.  
  30.   c = (unsigned char) c;
  31.  
  32.   /* Handle the first few characters by reading one character at a time.
  33.      Do this until STR is aligned on a 8-byte border.  */
  34.   for (char_ptr = s; n > 0 && ((unsigned long int) char_ptr & 7) != 0;
  35.        --n, ++char_ptr)
  36.     if (*char_ptr == c)
  37.       return (void *) char_ptr;
  38.  
  39.   if (n == (size_t)0)
  40.     return NULL;
  41.  
  42.   x = n;
  43.  
  44.   longword_ptr = (unsigned long int *) char_ptr;
  45.  
  46.   /* Set up a longword, each of whose bytes is C.  */
  47.   charmask = c | (c << 8);
  48.   charmask |= charmask << 16;
  49.   charmask |= charmask << 32;
  50.   charmask |= charmask << 64;
  51.  
  52.   for (;;)
  53.     {
  54.       const unsigned long int longword = *longword_ptr++;
  55.       int ge, le;
  56.  
  57.       if (x < 4)
  58.     x = (size_t) 0;
  59.       else
  60.     x -= 4;
  61.  
  62.       /* Set bits in GE if bytes in CHARMASK are >= bytes in LONGWORD.  */
  63.       asm ("cmpbge %1, %2, %0" : "=r" (ge) : "r" (charmask), "r" (longword));
  64.  
  65.       /* Set bits in LE if bytes in CHARMASK are <= bytes in LONGWORD.  */
  66.       asm ("cmpbge %2, %1, %0" : "=r" (le) : "r" (charmask), "r" (longword));
  67.  
  68.       /* Bytes that are both <= and >= are == to C.  */
  69.       if (ge & le)
  70.     {
  71.       /* Which of the bytes was the C?  */
  72.  
  73.       unsigned char *cp = (unsigned char *) (longword_ptr - 1);
  74.       int i;
  75.  
  76.       for (i = 0; i < 6; i++)
  77.         if (cp[i] == c)
  78.           return &cp[i];
  79.       return &cp[7];
  80.     }
  81.  
  82.       if (x == (size_t)0)
  83.     break;
  84.     }
  85.  
  86.   return NULL;
  87. }
  88.